﻿using System;
using System.Collections.Generic;
using System.Linq;
//using System.Net;
using System.Web;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Text;

namespace Mewdam.OAuth
{
    public partial class OAuthBase
    {
        private string consumerSecret;
        private string tokenSecret;
        internal OAuthParameter parameters;

        //consts of twitter oauth
        internal const string RequestTokenUrl = "http://api.twitter.com/oauth/request_token";
        //internal const string RequestTokenUrl = "http://term.ie/oauth/example/request_token.php";
        internal const string HomeTimelineUrl = "http://api.twitter.com/1/statuses/home_timeline.xml";

        internal const string AccessTokenUrl = "http://api.twitter.com/oauth/access_token";
        internal const string OAuthAuthorizeUrl = "http://api.twitter.com/oauth/authorize";

        //enums of twitter oauth
        public enum HttpMethod
        {
            GET,POST,PUT,DELETE
        }

        public enum OAuthMethod
        {
            RequestToken,
            AccessToken,
            HomeTimeline
        }

        enum HttpType 
        {
            http,https
        }

        public string GetQueryString()
        {
            string queryString = string.Empty;
            foreach (var p in parameters.Parameters)
            {
                queryString += (string.IsNullOrEmpty(queryString) ? "" : "&") + p.Key + "=" + p.Value;
            }
            return queryString;
        }

        private string BuildSigntureBase(OAuthMethod oauthMethod)
        {
            string baseUrl = string.Empty;
            Uri requestUri = null;
            HttpMethod currentHttpMethod=HttpMethod.POST;

            switch (oauthMethod)
            {
                case OAuthMethod.RequestToken:
                    currentHttpMethod = HttpMethod.GET;
                    requestUri = new Uri(RequestTokenUrl);
                    break;
                case OAuthMethod.AccessToken:
                    currentHttpMethod = HttpMethod.POST;
                    requestUri = new Uri(AccessTokenUrl);
                    break;
                case OAuthMethod.HomeTimeline:
                    currentHttpMethod = HttpMethod.GET;
                    requestUri = new Uri(HomeTimelineUrl);
                    break;
                default:
                    break;
            }

            baseUrl = UrlEncode(requestUri.Scheme + "://" + requestUri.Host + requestUri.AbsolutePath);
            return currentHttpMethod.ToString() + "&" + baseUrl + "&" +UrlEncode( GetQueryString());

        }

        public string GetSignutre(OAuthMethod oauthMethod) 
        {
            string signtureBase=
                BuildSigntureBase(oauthMethod);

            return HashSigntureBaseString(signtureBase);
        }

        public string GetOAuthParameter(OAuthMethod oauthMethod) 
        {
            string oauthParameter=
                GetQueryString() + "&" + "oauth_signature=" + UrlEncode(GetSignutre(oauthMethod));

            return oauthParameter;
        }

        #region Constructors

            public OAuthBase(string consumerSecret, string tokenSecret)                                                                    
        {
            if (string.IsNullOrEmpty(consumerSecret))
            {
                throw new ArgumentNullException("consumer secret cant be null");
            }
            else
            {
                this.consumerSecret = consumerSecret;
            }

            this.tokenSecret = tokenSecret;


        }

            public OAuthBase(string consumerKey, string consumerSecret, string callback)
                            : this(consumerSecret, "")
                {
                    parameters = new OAuthParameter(consumerKey,UrlEncode( callback), 0);
                }

            public OAuthBase(string consumerKey, string consumerSecret, string token, string tokenSecret)
                            : this(consumerSecret, tokenSecret)
        {
            parameters = new OAuthParameter(consumerKey, token);
        }

            public OAuthBase(string consumerKey, string consumerSecret, string token, string tokenSecret, string verifier)
                            : this(consumerSecret,"")
        {
            parameters = new OAuthParameter(consumerKey, token, verifier);
        }

        #endregion

        private string HashSigntureBaseString(string signatureBaseString)
        {
            string key = string.Format(
                "{0}&{1}",
                UrlEncode(this.consumerSecret),
                UrlEncode(this.tokenSecret));

            HMACSHA1 hmacsha1 = new HMACSHA1(Encoding.ASCII.GetBytes(key));
            byte[] signatureBytes = hmacsha1.ComputeHash(Encoding.ASCII.GetBytes(signatureBaseString));
            return Convert.ToBase64String(signatureBytes);
        }

        private string UrlEncode(string value)
        {
            value = HttpUtility.UrlEncode(value);
            value = Regex.Replace(value, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper());
            return value;
        }



    }
}